using EasyXaf.EntityDesigner.BusinessObjects;
using EasyXaf.EntityDesigner.BusinessObjects.Entities;
using EasyXaf.EntityDesigner.BusinessObjects.Entities.Associations;
using EasyXaf.EntityDesigner.BusinessObjects.Entities.EntityProperties;
using Microsoft.AspNetCore.Components;
using System.ComponentModel;

namespace EasyXaf.EntityDesigner.Editors.EntityAssociationEditors;

public sealed partial class EntityNode : IDisposable
{
    private string NodeTitle
    {
        get
        {
            if (!string.IsNullOrWhiteSpace(Entity.Caption))
            {
                if (Entity.Name != Entity.Caption)
                {
                    return $"{Entity.Name}({Entity.Caption})";
                }
            }
            return Entity.Name;
        }
    }

    private string NodeLocation
    {
        get
        {
            var entityDesign = Entity.GetEntityDesign(DomainModel);
            if (entityDesign != null)
            {
                return $"{entityDesign.Left},{entityDesign.Top}";
            }
            return "0,0";
        }
    }

    private string NodeConnections
    {
        get
        {
            var associations = Entity.Associations.Select(a =>
            {
                string parentSide = "1";
                string childSide = "*";

                if (a.AssociationType == AssociationType.OneToOne)
                {
                    parentSide = "1";
                    childSide = "1";
                }
                else if (a.AssociationType == AssociationType.OneToMany)
                {
                    parentSide = "1";
                    childSide = "*";
                }
                else
                {
                    parentSide = "*";
                    childSide = "*";
                }

                return $"{a.Oid},{a.Name},{a.Parent.Oid},{parentSide},{a.Child.Oid},{childSide}";
            });

            return string.Join(";", associations);
        }
    }

    [Parameter]
    public bool IsSelected { get; set; }

    [Parameter]
    public Entity Entity { get; set; }

    [Parameter]
    public DomainModel DomainModel { get; set; }

    [Parameter]
    public EntityUpdater EntityUpdater { get; set; }

    [Parameter]
    public EventCallback DoubleClicked { get; set; }

    private static bool IsNavigationProperty(EntityProperty property)
    {
        return property.PropertyType == PropertyType.Entity || property.PropertyType == PropertyType.EntityCollection;
    }

    private static string GetPropertyTitle(EntityProperty property)
    {
        if (!string.IsNullOrWhiteSpace(property.Caption))
        {
            if (property.Name != property.Caption)
            {
                return $"{property.Name}({property.Caption})";
            }
        }
        return property.Name;
    }

    private static string GetPropertyClassName(EntityProperty property)
    {
        var classNames = new List<string>
        {
            "d-flex",
            "align-items-center",
            "property"
        };

        if (IsNavigationProperty(property))
        {
            classNames.Add("navigation-property");
            classNames.Add("connection-target-endpoint");
        }

        return string.Join(" ", classNames);
    }

    private void EntityUpdater_EntityUpdated(object sender, Entity entity)
    {
        if (entity == Entity)
        {
            InvokeAsync(StateHasChanged);
        }
    }

    private void EntityNode_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        InvokeAsync(StateHasChanged);
    }

    protected override void OnInitialized()
    {
        base.OnInitialized();

        if (EntityUpdater != null)
        {
            EntityUpdater.EntityUpdated += EntityUpdater_EntityUpdated;
        }

        ((INotifyPropertyChanged)Entity).PropertyChanged += EntityNode_PropertyChanged;
    }

    public void Dispose()
    {
        if (EntityUpdater != null)
        {
            EntityUpdater.EntityUpdated -= EntityUpdater_EntityUpdated;
        }

        ((INotifyPropertyChanged)Entity).PropertyChanged -= EntityNode_PropertyChanged;
    }
}